package sg.edu.nus.iss.umpire.email;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import sg.edu.nus.iss.umpire.dao.jpa.CompetitionDaoImpl;
import sg.edu.nus.iss.umpire.domain.Competition;
import sg.edu.nus.iss.umpire.domain.CompetitionDay;
import sg.edu.nus.iss.umpire.domain.Session;
import sg.edu.nus.iss.umpire.domain.Umpire;
import sg.edu.nus.iss.umpire.support.AppConstants;
import sg.edu.nus.iss.umpire.support.HttpMethod;
import sg.edu.nus.iss.umpire.support.Service;
import sg.edu.nus.iss.umpire.support.ServiceConfig;
import sg.edu.nus.iss.umpire.support.ServiceContext;

@SuppressWarnings("serial")
@ServiceConfig(path = "processreminderrequest", method = HttpMethod.POST)
public class CompetitionReminderProcessorServlet implements Service {

	private static Logger log = Logger.getLogger(CompetitionReminderProcessorServlet.class.getCanonicalName());
	@Override
	public String serve(ServiceContext ctx) throws Exception {
		EntityManager em = ctx.getEntityManager();
		
		List<Competition> competitionList = new CompetitionDaoImpl(em).loadAll();
		List<Long> cids = new ArrayList<Long>();
		for (Competition c : competitionList) {
			cids.add(c.getKey());
		}
		ctx.commitCurrentTransaction();
		
		for (Long id : cids) {
			processCompetition(ctx, id);
		}
		return null;
	}
	
	private void processCompetition(ServiceContext ctx, Long id) throws ParseException, IOException {
		// TODO Auto-generated method stub
		Competition competition = ctx.getEntityManager().find(Competition.class, id);
		Map<Long, String > reminderCorpus = new HashMap<Long, String >();
		
		String dateFormat = "dd/MM/yyyy";
		DateFormat df = new SimpleDateFormat(dateFormat);
		
		TimeZone time = TimeZone.getTimeZone("GMT+8");
		time = TimeZone.getDefault();
		System.out.println(time);
		TimeZone.setDefault(time);
		
		Date dtNow = Calendar.getInstance().getTime();
		String dtNowStr = df.format(dtNow);
		
		Date startTime = new Date(); // current date time
		TimeZone pstTimeZone = TimeZone.getTimeZone("Asia/Singapore");
		DateFormat formatter = DateFormat.getDateInstance(); // just date, you might want something else
		formatter.setTimeZone(pstTimeZone);
		String formattedDate = formatter.format(startTime);
		Date realNow = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(formattedDate);
		for (CompetitionDay day : competition.getCompetitionDays()) {
			
			Date competitionDate = new SimpleDateFormat(dateFormat, Locale.ENGLISH).parse(day.getDate());
			
			log.log(Level.INFO, "competition date =" + day.getDate() + " now = " + formattedDate);
			if ( getIntervalDaysOfExitDate(realNow, competitionDate) == AppConstants.REMINDER_INTERVAL_IN_DAY )
			{
				for (Session session : day.getSessions()) {
					List<Long> comfiredUmpireIds = session.getConfirmedUmpire();
					String timeSlots = session.getSlotName();
					for (Long umpireKey : comfiredUmpireIds) {
						if(!reminderCorpus.containsKey(umpireKey)){
							reminderCorpus.put(umpireKey, "");
						}
						reminderCorpus.put(umpireKey, reminderCorpus.get(umpireKey) + buildTimeSlots(day.getDate(), timeSlots));
					}
				}
			}
			

		}
		
		ctx.commitCurrentTransaction(); // !important;  must commit the current transaction to start a transaction on a new Entity Group

		for(Long key: reminderCorpus.keySet()){
			sendConfirmEmailToUmpire(key, reminderCorpus.get(key), ctx.getEntityManager());
		}
		
	}

	private String buildTimeSlots(String competitionDate, String timeSlots)
			throws IOException
	{
		return ",(" + competitionDate + "," + timeSlots + ")";
	}
	
    /**
     * This method is used to get interval days of exitDateFrom and exitDateTo
     */
    private static int getIntervalDaysOfExitDate(Date exitDateFrom, Date exitDateTo){
        Calendar aCalendar = Calendar.getInstance();
        Calendar bCalendar = Calendar.getInstance();
        aCalendar.setTime(exitDateFrom);
        bCalendar.setTime(exitDateTo);
        int days = 0;
        while(aCalendar.before(bCalendar)){
            days++;
            aCalendar.add(Calendar.DAY_OF_YEAR, 1);
        }
        return days;
    }
	
	private void sendConfirmEmailToUmpire(Long umpireKey, String timeSlots, EntityManager em)
			throws IOException
	{
		  Umpire umpire = em.find(Umpire.class, umpireKey);
	      String umpireEmail = umpire.getEmail();	  
		  String subject = "Competition Reminder";
		  String msgBody = "Please attend the competition(s)" + timeSlots;
		  
		  msgBody += "on time. Thanks for your attending";		  
		  
		  // send email to umpires
		  MailService mailService = new MailService();
		  mailService.send(umpireEmail, subject, msgBody);
	}
    
}
